package xyz.heyaoshare.core.service.system.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.CacheableServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xyz.heyaoshare.common.constants.CacheKey;
import xyz.heyaoshare.common.entity.bo.ResultPage;
import xyz.heyaoshare.core.controller.system.dict.vo.req.*;
import xyz.heyaoshare.core.controller.system.dict.vo.resp.*;
import xyz.heyaoshare.core.entity.system.DictData;
import xyz.heyaoshare.core.enums.system.dict.DictDataStatusEnum;
import xyz.heyaoshare.core.mapper.system.DictDataMapper;
import xyz.heyaoshare.core.service.system.DictDataService;
import xyz.heyaoshare.utils.BeanUtils;
import xyz.heyaoshare.utils.StrUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static xyz.heyaoshare.exceptions.code.ErrorInfo.*;
import static xyz.heyaoshare.exceptions.customize.ServerException.exception;

/**
 * 字典数据 Service 实现类
 * @author YueHe
 * @version 0.0.1
 * @since 2025/6/25 下午2:07
 */
@Slf4j
@Service
@CacheConfig(cacheNames = CacheKey.DICT_DATA_SERVICE)
public class DictDataServiceImpl extends CacheableServiceImpl<DictDataMapper, DictData> implements DictDataService {

    @Resource
    private DictDataMapper dictDataMapper;

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Boolean insert(DictDataInsertReqVO reqVO) {
        // 1.校验类型名是否重复
        long count = QueryChain.of(DictData.class).eq(DictData::getValue, reqVO.getValue()).eq(DictData::getDictTypeId, reqVO.getDictTypeId()).count();
        if (count > 0) throw exception(DICT_VALUE_REPEAT);

        // 2.插入数据
        try {
            DictData dictData = new DictData()
                    .setDictTypeId(reqVO.getDictTypeId())
                    .setLabel(reqVO.getLabel())
                    .setValue(reqVO.getValue())
                    .setSort(reqVO.getSort())
                    .setStyle(reqVO.getStyle())
                    .setRemark(reqVO.getRemark());
            dictDataMapper.insert(dictData);

            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("新增字典数据失败", e);
            throw exception(INSERT_DICT_DATA_FAILED);
        }
    }

    @Override
    public ResultPage<DictDataPageRespVO> selectPage(DictDataPageReqVO reqVO) {
        // 1.查询数据
        Page<DictData> page = QueryChain.of(DictData.class)
                .eq(DictData::getDictTypeId, reqVO.getDictTypeId())
                .orderBy(DictData::getSort, Boolean.FALSE)
                .page(new Page<>(reqVO.getPage(), reqVO.getSize()));

        // 2.转换数据
        List<DictDataPageRespVO> items = Optional.ofNullable(page.getRecords()).orElseGet(ArrayList::new).stream().map(item -> {
            DictDataPageRespVO respVO = BeanUtils.copyProperties(item, DictDataPageRespVO.class);
            respVO.setStatusStr(DictDataStatusEnum.getLabel(item.getStatus()));
            return respVO;
        }).toList();

        // 3.返回数据
        return ResultPage.result(page.getTotalRow(), items);
    }

    @Override
    public List<DictDataListRespVO> selectList(DictDataListReqVO reqVO) {
        // 1.查询数据
        List<DictData> list = QueryChain.of(dictDataMapper)
                .eq(DictData::getStatus, DictDataStatusEnum.ENABLE.getValue())
                .orderBy(DictData::getSort, Boolean.FALSE)
                .orderBy(DictData::getCreateTime, Boolean.FALSE)
                .list();

        // 2.转换并返回数据
        return Optional.ofNullable(list).orElseGet(ArrayList::new).stream().map(item -> {
            DictDataListRespVO respVO = BeanUtils.copyProperties(item, DictDataListRespVO.class);
            respVO.setStatusStr(DictDataStatusEnum.getLabel(item.getStatus()));
            return respVO;
        }).toList();
    }

    @Override
    public DictDataDetailRespVO selectDetail(DictDataDetailReqVO reqVO) {
        DictData dictData = dictDataMapper.selectOneById(reqVO.getId());
        if (dictData == null) throw exception(DICT_DATA_NOT_EXIST);

        DictDataDetailRespVO respVO = BeanUtils.copyProperties(dictData, DictDataDetailRespVO.class);
        respVO.setStatusStr(DictDataStatusEnum.getLabel(dictData.getStatus()));
        return respVO;
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(DictDataDeleteReqVO reqVO) {
        try {
            UpdateChain.of(DictData.class).in(DictData::getId, reqVO.getDictDataIds()).remove();
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("字典数据删除失败", e);
            throw exception(DELETE_DICT_DATA_FAILED);
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateData(DictDataUpdateReqVO reqVO) {
        // 1.校验类型名是否重复
        long count = QueryChain.of(DictData.class).ne(DictData::getId, reqVO.getId()).eq(DictData::getValue, reqVO.getValue()).count();
        if (count > 0) throw exception(DICT_VALUE_REPEAT);

        // 2.更新数据
        try {
            UpdateChain.of(DictData.class)
                    .set(DictData::getDictTypeId, reqVO.getDictTypeId())
                    .set(DictData::getLabel, reqVO.getLabel())
                    .set(DictData::getValue, reqVO.getValue())
                    .set(DictData::getSort, reqVO.getSort())
                    .set(DictData::getStyle, reqVO.getStyle())
                    .set(DictData::getRemark, reqVO.getRemark(), StrUtils.isNotBlank(reqVO.getRemark()))
                    .eq(DictData::getId, reqVO.getId())
                    .update();
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("字典数据更新失败", e);
            throw exception(UPDATE_DICT_DATA_FAILED);
        }
    }

    @Override
    public List<DictDataByTypeRespVO> getByType(DictDataByTypeReqVO reqVO) {
        List<DictData> list = QueryChain.of(DictData.class)
                .eq(DictData::getDictTypeId, reqVO.getDictTypeId())
                .eq(DictData::getStatus, DictDataStatusEnum.ENABLE.getValue())
                .orderBy(DictData::getSort, Boolean.FALSE)
                .orderBy(DictData::getCreateTime, Boolean.FALSE)
                .list();

        return BeanUtils.copyToList(list, DictDataByTypeRespVO.class);
    }

    @Override
    public List<DictDataByTypeRespVO> getByTypeName(DictDataByTypeNameReqVO reqVO) {
        List<DictData> list = dictDataMapper.getByTypeName(reqVO);

        return Optional.ofNullable(list).orElseGet(ArrayList::new).stream().map(item -> {
            DictDataByTypeRespVO respVO = BeanUtils.copyProperties(item, DictDataByTypeRespVO.class);
            respVO.setStatusStr(DictDataStatusEnum.getLabel(item.getStatus()));
            return respVO;
        }).toList();
    }

    @Override
    @Cacheable
    public List<DictSimpleListRespVO> simpleList() {
        return dictDataMapper.simpleList();
    }

}